import tkinter as tk
from tkinter import  filedialog, messagebox
from datetime import datetime
from PIL import Image, ImageTk
from tkcalendar import DateEntry
import json
import os
import re

# 数据存储路径
DATA_FILE = "tasks.json"

def save_data(tasks):
    try:
        with open(DATA_FILE, 'w') as file:
            json.dump(tasks, file)
    except Exception as e:
        messagebox.showerror("Error saving data", str(e))

def load_data():
    try:
        if os.path.exists(DATA_FILE):
            with open(DATA_FILE, 'r') as file:
                return json.load(file)
        else:
            return []
    except Exception as e:
        messagebox.showerror("Error loading data", str(e))
        return []




window = tk.Tk()
window.title("To Do List")
window.geometry("800x600")

columns = ["To_Do", "In Progress", "Done"]
frames = {}
for col in columns:
    frame = tk.Frame(window, relief=tk.RAISED, borderwidth=1)
    frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    frames[col] = frame
    label = tk.Label(frame, text=col, bg='lightblue', font=('Arial', 12, 'bold'))
    label.pack(fill=tk.X)

def add_task(task_name, priority, due_date, image_path, dialog):
    try:
        if not task_name or not priority or not due_date:
            raise ValueError("you must enter all")
        datetime.strptime(due_date, '%Y-%m-%d')  
        create_card(frames["To_Do"], task_name, priority, due_date, image_path)
        dialog.destroy()
    except ValueError as ve:
        messagebox.showerror("error", str(ve))
    except Exception as e:
        messagebox.showerror("unknown error", str(e))
        create_card(frames["To_Do"], task_name, priority, due_date, image_path)
        dialog.destroy()
        save_tasks()  # 保存任务数据到JSON文件

def create_card_dialog():
    dialog = tk.Toplevel(window)
    dialog.title("Create New Task")
    dialog.geometry("400x300")
    
    task_name_var = tk.StringVar()
    priority_var = tk.StringVar(value="High")
    due_date_var = tk.StringVar(value=datetime.now().strftime('%Y-%m-%d'))
    image_path_var = tk.StringVar()

    task_name_label = tk.Label(dialog, text="Task Name:")
    task_name_label.pack(pady=5)
    task_name_entry = tk.Entry(dialog, textvariable=task_name_var)
    task_name_entry.pack(pady=5)
    
    priority_label = tk.Label(dialog, text="Priority:")
    priority_label.pack(pady=5)
    priority_options = ["High", "Medium", "Low"]
    priority_menu = tk.OptionMenu(dialog, priority_var, *priority_options)
    priority_menu.pack(pady=5)
    
    due_date_label = tk.Label(dialog, text="Due Date (YYYY-MM-DD):")
    due_date_label.pack(pady=5)
    due_date_entry = DateEntry(dialog, textvariable=due_date_var, date_pattern='yyyy-mm-dd')
    due_date_entry.pack(pady=5)

    def select_image():
        try:
            filename = filedialog.askopenfilename(title="Select Image", filetypes=[("Image Files", "*.png;*.jpg;*.jpeg;*.gif")])
            if filename:
                image_path_var.set(filename)
        except Exception as e:
            messagebox.showerror("Image Selection Error", str(e))

    def on_confirm():
        if not task_name_var.get() or not priority_var.get() or not due_date_var.get():
            messagebox.showerror("Input Error", "All fields are required.")
            return
        add_task(task_name_var.get(), priority_var.get(), due_date_entry.get_date().strftime('%Y-%m-%d'), image_path_var.get(), dialog)

    confirm_button = tk.Button(dialog, text="Confirm", command=on_confirm)
    confirm_button.pack(pady=10)
    select_image_button = tk.Button(dialog, text="Select Image", command=select_image)
    select_image_button.pack(pady=5)

def create_card(frame, task_name, priority, due_date, image_path):
    try:
        card_frame = tk.Frame(frame, relief=tk.RAISED, borderwidth=1, padx=10, pady=10)
        card_frame.pack(fill=tk.X, pady=5)

        task_label = tk.Label(card_frame, text=f"Task: {task_name}", anchor='w')
        task_label.pack(fill=tk.X)
        priority_label = tk.Label(card_frame, text=f"Priority: {priority}", anchor='w')
        priority_label.pack(fill=tk.X)
        due_date_label = tk.Label(card_frame, text=f"Due Date: {due_date}", anchor='w')
        due_date_label.pack(fill=tk.X)
        edit_button = tk.Button(card_frame, text="Edit", command=lambda: edit_task(card_frame, task_name, priority, due_date, image_path))
        edit_button.pack(anchor='s')
        delete_button = tk.Button(card_frame, text="Delete", command=lambda: delete_card(card_frame))
        delete_button.pack(anchor='s')
        created_time_label = tk.Label(card_frame, text=f"Created: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", anchor='w')
        created_time_label.pack(fill=tk.X)

        if image_path:
            try:
                img = Image.open(image_path)
                img = img.resize((100, 100))
                img = ImageTk.PhotoImage(img)
                image_label = tk.Label(card_frame, image=img)
                image_label.image = img
                image_label.pack()
            except IOError:
                messagebox.showerror("Error loading image", "The image file could not be opened or read.")
    except Exception as e:
        messagebox.showerror("Error creating card", str(e))

def delete_card(card_frame):
    try:
        card_frame.destroy()
    except Exception as e:
        messagebox.showerror("Error deleting card", str(e))

def edit_task(card_frame, current_task_name, current_priority, current_due_date, current_image_path):
    try:
        edit_dialog = tk.Toplevel(window)
        edit_dialog.title("Edit Task")
        edit_dialog.geometry("400x300")

        task_name_var = tk.StringVar(value=current_task_name)
        priority_var = tk.StringVar(value=current_priority)
        due_date_var = tk.StringVar(value=current_due_date)
        image_path_var = tk.StringVar(value=current_image_path)

        task_name_label = tk.Label(edit_dialog, text="Task Name:")
        task_name_label.pack(pady=5)
        task_name_entry = tk.Entry(edit_dialog, textvariable=task_name_var)
        task_name_entry.pack(pady=5)

        priority_label = tk.Label(edit_dialog, text="Priority:")
        priority_label.pack(pady=5)
        priority_options = ["High", "Medium", "Low"]
        priority_menu = tk.OptionMenu(edit_dialog, priority_var, *priority_options)
        priority_menu.pack(pady=5)

        due_date_label = tk.Label(edit_dialog, text="Due Date:")
        due_date_label.pack(pady=5)
        due_date_entry = DateEntry(edit_dialog, textvariable=due_date_var, date_pattern='yyyy-mm-dd')
        due_date_entry.pack(pady=5)

        def select_image():
            try:
                filename = filedialog.askopenfilename(title="Select Image", filetypes=[("Image Files", "*.png;*.jpg;*.jpeg;*.gif")])
                if filename:
                    image_path_var.set(filename)
            except Exception as e:
                messagebox.showerror("wrongly select picture", str(e))

        confirm_button = tk.Button(edit_dialog, text="Confirm", command=lambda: save_edits(card_frame, task_name_var.get(), priority_var.get(), due_date_entry.get_date().strftime('%Y-%m-%d'), image_path_var.get(), edit_dialog))
        confirm_button.pack(pady=10)
        select_image_button = tk.Button(edit_dialog, text="Select Image", command=select_image)
        select_image_button.pack(pady=5)
    except Exception as e:
        messagebox.showerror("Error editing task", str(e))

def save_edits(card_frame, new_task_name, new_priority, new_due_date, new_image_path, dialog):
    try:
        for widget in card_frame.winfo_children():
            if isinstance(widget, tk.Label) and widget.cget('text').startswith("Task:"):
                widget.config(text=f"Task: {new_task_name}")
            elif isinstance(widget, tk.Label) and widget.cget('text').startswith("Priority:"):
                widget.config(text=f"Priority: {new_priority}")
            elif isinstance(widget, tk.Label) and widget.cget('text').startswith("Due Date:"):
                widget.config(text=f"Due Date: {new_due_date}")
            elif isinstance(widget, tk.Label) and hasattr(widget, 'image'):
                if new_image_path:
                    try:
                        img = Image.open(new_image_path)
                        img = img.resize((100, 100))
                        img = ImageTk.PhotoImage(img)
                        widget.config(image=img)
                        widget.image = img
                    except IOError:
                        messagebox.showerror("Error loading image", "The image file could not be opened or read.")
        dialog.destroy()
    except Exception as e:
        messagebox.showerror("Error saving edits", str(e))
    dialog.destroy()
    save_tasks()  # 保存任务数据到JSON文件

def save_tasks():
    try:
        tasks = []
        for col in columns:
            for child in frames[col].winfo_children():
                if isinstance(child, tk.Frame):
                    task_data = {
                        'name': '',
                        'priority': '',
                        'due_date': '',
                        'image_path': '',
                    }
                    for widget in child.winfo_children():
                        if isinstance(widget, tk.Label):
                            text = widget.cget('text')
                            if text.startswith('Task:'):
                                task_data['name'] = text.split(': ')[1]
                            elif text.startswith('Priority:'):
                                task_data['priority'] = text.split(': ')[1]
                            elif text.startswith('Due Date:'):
                                task_data['due_date'] = text.split(': ')[1]
                        elif isinstance(widget, tk.PhotoImage):
                            # 假设你有一个方式获取图片路径
                            task_data['image_path'] = widget.file
                    tasks.append(task_data)
        save_data(tasks)
    except Exception as e:
        messagebox.showerror("Error saving tasks", str(e))

def create_cards_from_data(data):
    try:
        for task in data:
            create_card(frames["To_Do"], task['name'], task['priority'], task['due_date'], task['image_path'])
    except Exception as e:
        messagebox.showerror("Error creating cards", str(e))

tasks_data = load_data()
create_cards_from_data(tasks_data)

button = tk.Button(window, text="Create", command = create_card_dialog)
button.pack()
def on_closing():
    save_tasks()
    window.destroy()

window.protocol("WM_DELETE_WINDOW", on_closing)

window.mainloop()